import { Inject, Provide } from '@midwayjs/core';
import { Repository } from 'typeorm';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { StudentWristband } from '@entity/firmware/student_wristband.entity';
import { Student } from '@entity/firmware/student.entity';
import { Wristband } from '@entity/firmware/wristband.entity';
import { StudentService } from './student.service';
import { GatewayService } from './gateway.service';
import { WristbandService } from './wristband.service';
import { resBuild } from '@utils/resBuild';

@Provide()
export class StudentWristbandService {
  @InjectEntityModel(StudentWristband)
  studentWristbandModel: Repository<StudentWristband>;
  @InjectEntityModel(Student)
  student: Repository<Student>
  @InjectEntityModel(Wristband)
  wristband: Repository<Wristband>
  @Inject()
  studentService: StudentService;
  @Inject()
  gatewayService: GatewayService;
  @Inject()
  wristbandService: WristbandService;


  formatMacToStandard = (mac) => {
    // 移除所有非字母数字字符
    let cleanMac = mac.replace(/[^a-fA-F0-9]/g, '').toUpperCase();

    // 补全冒号（如果长度足够）
    if (cleanMac.length === 12) {
      return cleanMac.match(/.{2}/g).join(':');
    }

    // 如果长度不足，返回 null（无法标准化）
    return null;
  };




  // 添加关联（包含关系查询）
  async createAssociation(params) {
    const { mac, sid } = params;
    // 首先验证学生和手环是否存在
    const student = await this.student.findOne({ where: { id: sid } });
    if (!student) {
      throw new Error('学生不存在');
    }
    const standardMac = this.formatMacToStandard(mac);
    let wristband;
    if (standardMac) {
      // 如果能标准化，精确查询
      wristband = await this.wristband.findOne({
        where: { mac: standardMac }
      });
    } else {
      // 如果不能标准化（如输入不完整），报错
      throw new Error('请输入正确的手环地址！');
    }

    if (!wristband) {
      throw new Error('手环不存在！');
    }
    // 检查是否已存在相同的关联
    const existingAssociation = await this.studentWristbandModel.findOne({
      where: { mac, sid }
    });
    if (existingAssociation) {
      throw new Error('该手环已关联到此学生');
    }
    // 检查手环是否已关联到其他学生
    const wristbandInUse = await this.studentWristbandModel.findOne({
      where: { mac }
    });
    if (wristbandInUse) {
      throw new Error('该手环已关联到其他学生');
    }
    const association = new StudentWristband();
    association.mac = mac;
    association.sid = sid;
    // 保存时会自动验证外键约束
    return await this.studentWristbandModel.save(association);
  }

  // 根据学生ID查找手环（包含手环详细信息）
  async findWristbandByStudentId(sid: number) {
    const result = await this.studentWristbandModel.findOne({
      where: { sid },
      relations: ['wristband'] // 加载关联的手环信息
    });
    return resBuild.data(result)
  }

  // 根据手环MAC查找学生（包含学生详细信息）
  async findStudentByWristbandMac(mac: string) {
    return await this.studentWristbandModel.findOne({
      where: { mac },
      relations: ['student'] // 加载关联的学生信息
    });
  }

  // 删除关联
  async deleteAssociation(params) {
    const { mac, sid } = params
    return await this.studentWristbandModel.delete({ mac, sid });
  }

  // 班级批量给学生分配手环
  // 获取未分配的手环并进行分配
  async setStuWb(params) {
    try {
      const { class_id } = params
      // 1. 获取未分配手环的 MAC 地址
      const unassignedWristbands = await this.wristband
        .createQueryBuilder('wristband')
        .leftJoin('wristband.student_wristband', 'student_wristband')
        .where('student_wristband.sid IS NULL') // 筛选没有分配给学生的手环
        .andWhere('wristband.fw_name IS NOT NULL AND wristband.fw_name != ""') // 过滤出 fw_name 不为空的手环
        .andWhere('wristband.fw_name != "bootloader"') // 过滤出 fw_name 为 bootloader 的手环
        .andWhere('wristband.deleted = :deleted', { deleted: false })
        .getMany();

      // 2. 获取该班级所有学生
      const students = await this.student
        .createQueryBuilder('student')
        .where('student.class_id = :class_id', { class_id })
        .getMany();

      // 获取手环数量和学生数量
      const wristbandCount = unassignedWristbands.length;
      const studentCount = students.length;

      // 如果学生多于手环，回收已分配的手环
      if (wristbandCount < studentCount) {
        const alreadyAssignedWristbands = await this.studentWristbandModel
          .createQueryBuilder('student_wristband')
          .leftJoinAndSelect('student_wristband.student', 'student')
          .where('student.class_id = :class_id', { class_id })
          .getMany();

        // 回收已分配的手环
        for (const assigned of alreadyAssignedWristbands) {
          await this.studentWristbandModel.remove(assigned); // 删除学生与手环的关联
        }
      }

      // 3. 进行分配：一对一分配学生和手环
      const updatePromises = students.slice(0, wristbandCount).map(async (student, index) => {
        const wristband = unassignedWristbands[index];

        // 创建学生与手环的关联
        const studentWristband = new StudentWristband();
        studentWristband.sid = student.id;
        studentWristband.mac = wristband.mac;

        // 保存关联关系
        await this.studentWristbandModel.save(studentWristband);
      });

      // 等待所有更新操作完成
      await Promise.all(updatePromises);

      return {
        assignedCount: updatePromises.length,
        unassignedCount: studentCount - wristbandCount,
      };
    } catch (error) {
      console.error('分配手环时发生错误:', error);
      throw new Error('分配手环时发生错误');
    }
  }



  // 更新学生关联的手环
  async updateStudentWristband(sid: number, newMac: string) {
    // 先删除旧的关联（如果存在）
    await this.studentWristbandModel.delete({ sid });

    // 创建新的关联
    const association = new StudentWristband();
    association.mac = newMac;
    association.sid = sid;
    return await this.studentWristbandModel.save(association);
  }

  // 更新手环关联的学生
  async updateWristbandStudent(mac: string, newSid: number) {
    // 先删除旧的关联（如果存在）
    await this.studentWristbandModel.delete({ mac });

    // 创建新的关联
    const association = new StudentWristband();
    association.mac = mac;
    association.sid = newSid;
    return await this.studentWristbandModel.save(association);
  }
}
